﻿#pragma once

#include "../../repo/src/include/root/rpc_transport.h"

#include <functional>
#include <memory>
#include <string>

namespace kratos {
namespace ws {

class WebSocketChannel;

using WebSocketChannelPtr = std::shared_ptr<kratos::ws::WebSocketChannel>;

/**
 * @brief 用户回调事件
 */
enum class WebSocketEvent {
  ACCEPT, ///< 接受一个新连接
  CLOSE,  ///< 管道关闭
  RECV,   ///< 接收到数据
};

using WebSocketCallback =
    std::function<void(WebSocketEvent, WebSocketChannelPtr)>;

class WebSocketServer {
public:
  virtual ~WebSocketServer() {}
  /**
   * @brief 启动
   * @param callback 用户事件回调
   * @return true或false
   */
  virtual auto startup(WebSocketCallback callback) -> bool = 0;
  /**
   * @brief 关闭
   * @return true或false
   */
  virtual auto shutdown() -> bool = 0;
  /**
   * @brief 获取WebSocket管道
   * @param channel_id 管道ID
   * @return WebSocket管道
  */
  virtual auto get_channel(std::uint64_t channel_id) -> WebSocketChannelPtr = 0;
};

class WebSocketClient {
public:
  virtual ~WebSocketClient() {}
  /**
   * @brief 启动
   * @param callback 用户事件回调
   * @return true或false
   */
  virtual auto startup(WebSocketCallback callback) -> bool = 0;
  /**
   * @brief 关闭
   * @return true或false
   */
  virtual auto shutdown() -> bool = 0;
};

/**
 * @brief Websocket管道
*/
class WebSocketChannel : public rpc::Transport {
public:
  virtual ~WebSocketChannel() {}
  virtual int send(const char* data, const int size) = 0;
  virtual int peek(char* data, const int size) = 0;
  virtual int recv(char* data, const int size) = 0;
  virtual int skip(const int size) = 0;
  virtual int size() = 0;
  virtual bool isClose() = 0;
  virtual void close() = 0;
  /**
   * @brief 发送文本
   * @param data 文本
   * @return 发送的字节数
   */
  virtual auto send(const std::string &data) -> int = 0;
  /**
   * @brief 读取文本
   * @param [OUT] str 读取到的文本
   * @return 读取到的字节数
   */
  virtual auto recv(std::string &str) -> int = 0;
  /**
   * @brief 获取管道ID
   * @return 管道ID
  */
  virtual auto get_id()->std::uint64_t = 0;
};

} // namespace ws
} // namespace kratos
